home *** CD-ROM | disk | FTP | other *** search
/ Aminet 39 / Aminet 39 (2000)(Schatztruhe)[!][Oct 2000].iso / Aminet / game / shoot / Orbit_src.lha / Orbit / source / orbit.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-07-04  |  14.5 KB  |  727 lines

  1. /*
  2.     Amiga port by Oliver Gantert
  3.  
  4.     27.04.2000 - fixed some compiler warnings
  5.     21.06.2000 - Junk(), PieceOfJunk() and LookAt() optimized
  6. */
  7. /*
  8.  
  9. ORBIT, a freeware space combat simulator
  10. Copyright (C) 1999  Steve Belczyk <steve1@genesis.nred.ma.us>
  11.  
  12. This program is free software; you can redistribute it and/or
  13. modify it under the terms of the GNU General Public License
  14. as published by the Free Software Foundation; either version 2
  15. of the License, or (at your option) any later version.
  16.  
  17. This program is distributed in the hope that it will be useful,
  18. but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20. GNU General Public License for more details.
  21.  
  22. You should have received a copy of the GNU General Public License
  23. along with this program; if not, write to the Free Software
  24. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  25.  
  26. */
  27.  
  28. #define ALLOCATE
  29. #include "orbit.h"
  30.  
  31. #ifdef AMIGA
  32. static char *amiga_version_string =
  33. "$VER: Orbit " AMIGA_VERSION " (" AMIGA_DATE ") Port of " VERSION;
  34.  
  35. struct Library *LucyPlayBase = NULL;
  36. #endif /* AMIGA */
  37.  
  38. int tm, frames, total_frames;
  39.  
  40. int main (int argc, char **argv)
  41. {
  42.   if (!(LucyPlayBase = (struct Library *)OpenLibrary("lucyplay.library", 1)))
  43.   {
  44.     printf("Couldn't open 'lucyplay.library'.\n");
  45.     return(0);
  46.   }
  47.  
  48.   /* Kick random number generator */
  49.   srand (time(NULL));
  50.  
  51.   /* Check for joystick */
  52.   InitJoy();
  53.  
  54.   /* Init the performance timer */
  55.   InitTimer();
  56.  
  57.   /* Set up the player viewpoint, etc */
  58.   InitPlayer();
  59.  
  60.   /* Initialize all sorts of other stuff */
  61.   InitStuff();
  62.  
  63.   /* Open a window */
  64.   OpenWindow (argc, argv);
  65.  
  66.   frames = 0;
  67.   total_frames = 1;
  68.   tm = time(NULL);
  69.  
  70.   /* Loop forever */
  71.   glutMainLoop();
  72.  
  73.   return(0);
  74. }
  75.  
  76. void OpenWindow (int argc, char **argv)
  77. /*
  78.  *  Open a window
  79.  */
  80. {
  81.   char *p;
  82.  
  83.   glutInit (&argc, argv);
  84.   glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
  85.  
  86.   glutInitWindowPosition (0, 0);
  87.   glutInitWindowSize (ScreenWidth, ScreenHeight);
  88.  
  89.   if (!strcasecmp (gamemode, "no"))
  90.   {
  91.     glutCreateWindow ("Orbit");
  92.   }
  93.   else
  94.   {
  95.     glutGameModeString (gamemode);
  96.     glutEnterGameMode();
  97.   }
  98.  
  99.   if (fullscreen) glutFullScreen ();
  100.  
  101.   glutDisplayFunc (DrawScene);
  102.   glutReshapeFunc (Reshape);
  103.  
  104.   /* Define lights, etc */
  105.   Lights();
  106.   glEnable (GL_DEPTH_TEST);
  107.   glEnable (GL_CULL_FACE);
  108.  
  109.   /* Put up some driver info */
  110.   p = (char *) glGetString (GL_VENDOR);
  111.   Log ("OpenWindow: OpenGL vendor: %s", p);
  112.   p = (char *) glGetString (GL_RENDERER);
  113.   Log ("OpenWindow: OpenGL renderer: %s", p);
  114.   p = (char *) glGetString (GL_VERSION);
  115.   Log ("OpenWindow: OpenGL version: %s", p);
  116. }
  117.  
  118. void CreateUniverse ()
  119. /*
  120.  *  And Then There Was Light
  121.  */
  122. {
  123.   /* Initialize keyboard */
  124.   InitKeyboard();
  125.  
  126.   /* Initialize the mouse */
  127.   InitMouse();
  128.  
  129.   /* Construct the starfield display list */
  130.   MakeStarList();
  131.  
  132.   /* Initialize planets */
  133.   InitPlanets(); 
  134.   
  135.   /* Init AC3D textures */ 
  136.   InitTextures();
  137.  
  138.   /* Ring stuff */
  139.   InitRings();
  140.  
  141.   /* Init the HUD */
  142.   InitHud();
  143.  
  144.   /* Initialize sound */
  145.   InitSound();
  146.  
  147.   /* Initialize the network */
  148.   InitNetwork();
  149.  
  150.   /* Okay, load a mission */
  151.   if (mission.fn[0] != 0)
  152.   {
  153.     /* Load mission from prefs file */
  154.     ReadMission (mission.fn);
  155.   }
  156.   else
  157.   {
  158.     /* Read default mission */
  159.     ReadMission ("train01.msn");
  160.   }
  161. }
  162.  
  163. void DrawScene()
  164. /*
  165.  *  Draw the scene
  166.  */
  167. {
  168.   double v[3], t;
  169.  
  170.   /* if (am_client) Log ("!!! DrawScene()"); */
  171.  
  172.   /* Are we still initializing? */
  173.   if (state == STATE_INIT)
  174.   {
  175.     /* Create everything */
  176.     CreateUniverse();
  177.  
  178.     /* Mark new state */
  179.     state = STATE_NORMAL;
  180.   }
  181.  
  182.   /* Figure out how many seconds (in deltaT) have elapsed since the last
  183.     time we were here */
  184.   /* if (am_client) Log ("!!! DeltaTime()"); */
  185.   DeltaTime();
  186.  
  187.   /* Handle the network */
  188.   /* if (am_client) Log ("!!! DoNetwork()"); */
  189.   DoNetwork();
  190.  
  191.   /* Read the keyboard */
  192.   /* if (am_client) Log ("!!! Keyboard()"); */
  193.   Keyboard();
  194.  
  195.   /* Handle the joystick */
  196.   /* if (am_client) Log ("!!! Joystick()"); */
  197.   if (joy_available && !paused) JoyStick();
  198.  
  199.   /* Do the mouse */
  200.   /* if (am_client) Log ("!!! DoMouse()"); */
  201.   if (mouse_control && !paused) DoMouse();
  202.  
  203.   /* Move the planets */
  204.   if (orbit) MovePlanets();
  205.  
  206.   /* Move the player */
  207.   /* if (am_client) Log ("!!! UpdatePlayer()"); */
  208.   if (!paused) UpdatePlayer ();
  209.  
  210.   /* Move the targets */
  211.   /* if (am_client) Log ("!!! MoveTargets()"); */
  212.   if (!paused) MoveTargets ();
  213.  
  214.   /* Move the missiles */
  215.   /* if (am_client) Log ("!!! MoveMissiles()"); */
  216.   if (!paused) MoveMissiles ();
  217.  
  218.   /* Process any outstanding events */
  219.   /* if (am_client) Log ("!!! DoEvents()"); */
  220.   DoEvents();
  221.  
  222.   /* Clear the screen */
  223.   if (palette_flash == 2)
  224.   {
  225.     /* Flash red */
  226.     palette_flash = 0;
  227.     glClearColor (1.0, 0.0, 0.0, 0.0);
  228.   }
  229.   else if (palette_flash > 0)
  230.   {
  231.     /* Flash white */
  232.     palette_flash = 0;
  233.     glClearColor (1.0, 1.0, 1.0, 0.0);
  234.   }
  235.   else
  236.   {
  237.     glClearColor (0.0, 0.0, 0.0, 0.0);
  238.   }
  239.   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  240.  
  241.   /* Set up viewing transformation */
  242.   glMatrixMode (GL_MODELVIEW);
  243.   glLoadIdentity();
  244.  
  245.   /* Compute a point along line of sight */
  246.   Vadd (v, player.pos, player.view);
  247.  
  248.   gluLookAt (0.0, 0.0, 0.0,
  249.   player.view[0], player.view[1], player.view[2],
  250.   player.up[0], player.up[1], player.up[2]);
  251.  
  252.   /* Draw the star field here */
  253.   if (starfield) DrawStars();
  254.  
  255.   Lights();
  256.  
  257.   /* Draw the world */
  258.   /* if (am_client) Log ("!!! DrawWorld()"); */
  259.   DrawWorld();
  260.  
  261.   /* Do some 2-D stuff just to prove I can */
  262.   /* if (am_client) Log ("!!! Hud()"); */
  263.   Hud();
  264.  
  265.   /* Swap buffers */
  266.   glFlush();
  267.   glutSwapBuffers();
  268.  
  269.   /* Keep on Displayin' */
  270.   glutPostRedisplay();
  271.  
  272.   frames++;
  273.   total_frames++;
  274.   if (0 == (frames % 50))
  275.   {
  276.     t = Time();
  277.  
  278.     fps = 50.0 / t;
  279.     frames = 0;
  280.  
  281.     recv_bps = ((double) recv_bytes) / t;
  282.     xmit_bps = ((double) xmit_bytes) / t;
  283.     recv_bytes = xmit_bytes = 0;
  284.  
  285.     tm = time (NULL);
  286.   }
  287. }
  288.  
  289. void DrawSplash()
  290. /*
  291.  *  Draw minimal screen for startup splash
  292.  */
  293. {
  294.   double v[3];
  295.   int tmphud;
  296.  
  297.   Reshape (ScreenWidth, ScreenHeight);
  298.  
  299.   glClearColor (0.0, 0.0, 0.0, 0.0);
  300.   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  301.  
  302.   /* Set up viewing transformation */
  303.   glMatrixMode (GL_MODELVIEW);
  304.   glLoadIdentity();
  305.  
  306.   /* Compute a point along line of sight */
  307.   Vadd (v, player.pos, player.view);
  308.  
  309.   gluLookAt (player.pos[0], player.pos[1], player.pos[2],
  310.   v[0], v[1], v[2],
  311.   player.up[0], player.up[1], player.up[2]);
  312.  
  313.   /* Draw the star field here */
  314.   /* if (starfield) DrawStars(); */
  315.  
  316.   /* Do some 2-D stuff just to prove I can */
  317.   tmphud = drawhud;
  318.   drawhud = 0;
  319.   Hud();
  320.   drawhud = tmphud;
  321.  
  322.   /* Swap buffers */
  323.   glFlush();
  324.   glutSwapBuffers();
  325.  
  326.   /* Keep on Displayin' */
  327.   glutPostRedisplay();
  328. }
  329.  
  330. void Reshape (GLsizei w, GLsizei h)
  331. {
  332.   ScreenWidth = w;
  333.   ScreenHeight = h;
  334.  
  335.   glMatrixMode (GL_PROJECTION);
  336.   glLoadIdentity();
  337.   gluPerspective (fov, (double)w/(double)h, clipnear, clipfar);
  338.   glMatrixMode (GL_MODELVIEW);
  339.   glViewport (0, 0, w, h);
  340.  
  341.   /* Recompute the HUD stuff */
  342.   InitHud();
  343. }
  344.  
  345. static float MaterialColor[] = {
  346.   1.0, 1.0, 1.0, 1.0}
  347. ;
  348. static float JunkColor[] = {
  349.   0.7, 0.7, 0.7, 1.0}
  350. ;
  351. static double MissileColor[] = {
  352.   1.0, 1.0, 0.0, 1.0}
  353. ;
  354. static float TargetColor[] = {
  355.   1.0, 0.5, 0.0, 1.0}
  356. ;
  357.  
  358. void DrawWorld ()
  359. /*
  360.  *  Draw the world
  361.  */
  362. {
  363.   /* Draw planet */
  364.   DrawPlanets();
  365.  
  366.   /* Draw space junk */
  367.   if (junk)
  368.   {
  369.     glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, JunkColor);
  370.     Junk();
  371.   }
  372.  
  373.   /* Draw missiles */
  374.   DrawMissiles ();
  375.  
  376.   /* Draw targets */
  377.   DrawTargets();
  378.  
  379.   /* Draw explosions */
  380.   DrawBooms ();
  381.  
  382.   /* Draw planetary rings */
  383.   DrawRings();
  384.  
  385.   /* Show names of things */
  386.   if (show_names) ShowNames();
  387. }
  388.  
  389. void Print (void *font, char *string)
  390. {
  391.   int len, i;
  392.  
  393.   len = strlen (string);
  394.   for (i=0; i<len; i++)
  395.   {
  396.     glutBitmapCharacter (font, string[i]);
  397.   }
  398. }
  399.  
  400. void InitStuff()
  401. /*
  402.  *  Misc initilization
  403.  *
  404.  *  DON'T PUT ANY OPENGL STUFF IN HERE!  THE WINDOW HASN'T EVEN BEEN OPENED YET!!!
  405.  */
  406. {
  407.   vulnerable = 1;
  408.   joy_throttle = 0;
  409.   deadzone = DEADZONE;
  410.   absT = 0.0;
  411.   starfield = 1;
  412.   drawhud = 1;
  413.   showfps = 0;
  414.   gravity = 0;
  415.   junk = 1;
  416.   palette_flash = 0;
  417.   sound = 1;
  418.   show_names = 0;
  419.   screen_shot_num = 0;
  420.   rings = 1;
  421.   textures = 1;
  422.   mission.fn[0] = 0;
  423.   paused = 0;
  424.   mouse_control = 1;
  425.   strcpy (gamemode, "no");
  426.   fullscreen = 0;
  427.   player.flightmodel = FLIGHT_NEWTONIAN;
  428.   strcpy (player.name, "Sparky");
  429.   strcpy (player.model, "light2.tri");
  430.   ring_sectors = RING_SECTORS;
  431.   stacks0 = 3;
  432.   slices0 = 7;
  433.   stacks1 = 6;
  434.   slices1 = 13;
  435.   stacks2 = 12;
  436.   slices2 = 24;
  437.   mouse.flipx = 0;
  438.   mouse.flipy = 0;
  439.   state = STATE_INIT;
  440.   realdistances = 0;
  441.   fov = 90.0;
  442.   text.yes = 0;
  443.   text.buf[0] = 0;
  444.   text.index = 0;
  445.   text.prompt[0] = 0;
  446.   text.func = NULL;
  447.   fullstop = 1;
  448.   player.still = 1;
  449.   draw_orbits = 0;
  450.   orbit = 0;
  451.   compression = 1.0; 
  452.   player.viewlock = 0.0; 
  453.   server.port = ORBIT_PORT; 
  454.   superwarp = 1; 
  455. #ifndef AMIGA
  456.   clipnear = 0.001;
  457.   clipfar = 100000.0; 
  458. #else
  459.   clipnear = 0.002;
  460.   clipfar = 50000.0;
  461. #endif
  462.  
  463.   /* Set initial screen size */
  464.   ScreenWidth = SCREENWIDTH;
  465.   ScreenHeight = SCREENHEIGHT;
  466.  
  467.   /* Initialize the log file */
  468.   InitLog();
  469.  
  470.   Log ("InitStuff: ORBIT Version %s", VERSION);
  471.  
  472.   /* Read the preferences file */
  473.   ReadPrefs();
  474.  
  475.   /* Read stars data file */
  476.   ReadStars();
  477.  
  478.   /* Initialize the message console */
  479.   InitConsole();
  480.  
  481.   /* Initialize the message system */
  482.   InitMessage();
  483.  
  484.   /* Initialize the object models */
  485.   InitModels();
  486.  
  487.   /* Initialize the missiles */
  488.   InitMissiles();
  489.  
  490.   /* Weapons */
  491.   InitWeapons();
  492.  
  493.   /* Initialize explosions */
  494.   InitBooms();
  495.  
  496.   /* Initialize lights */
  497.   InitLights();
  498.  
  499.   /* Initialize targets */
  500.   InitTargets();
  501.  
  502.   /* Initialize events */
  503.   InitEvents();
  504.  
  505.   /* Self-promotion */
  506.   Cprint ("Orbit %s, by Steve Belczyk <orbit@genesis.nred.ma.us>", VERSION);
  507.   Cprint ("http://genesis.ne.mediaone.net/orbit");
  508.   #ifdef AMIGA_VERSION
  509.   Cprint ("Amiga port %s, by Oliver Gantert <lucyg@t-online.de>", AMIGA_VERSION);
  510.   Cprint ("http://home.t-online.de/home/LucyG");
  511.   #endif
  512. }
  513.  
  514. double Theta (double *v)
  515. /*
  516.  *  Compute angle vector v points to
  517.  */
  518. {
  519.   double th;
  520.  
  521.   th = (double) acos ((double) v[0]);
  522.   th = th * 57.29577951308;
  523.   if (v[1] < 0.0) th = (-th);
  524.  
  525.   return (th);
  526. }
  527.  
  528. #ifdef WIN32MOUSE
  529. Mouse()
  530. /*
  531.  *  Process the mouse
  532.  */
  533. {
  534.   GetCursorPos (&point);
  535.   mouse_x = point.x;
  536.   mouse_y = point.y;
  537.  
  538.   if (mouse_x > last_mouse_x) player.move_right = 1.0;
  539.   if (mouse_x < last_mouse_x) player.move_left = 1.0;
  540.   if (mouse_y > last_mouse_y) player.move_up = 1.0;
  541.   if (mouse_y < last_mouse_y) player.move_down = 1.0;
  542.  
  543.   last_mouse_x = last_mouse_y = 400;
  544.  
  545.   SetCursorPos (400, 400);
  546. }
  547. #endif
  548.  
  549. void Gravity (double *deltav, double *pos)
  550. /*
  551.  *  Compute change in velocity due to planet's gravity
  552.  */
  553. {
  554.   double r, rr, dv, dp[3], v[3];
  555.   int p;
  556.  
  557.   deltav[0] = deltav[1] = deltav[2] = 0.0;
  558.  
  559.   for (p=0; p<NPLANETS; p++)
  560.   {
  561.     /* Distance to planet */
  562.     Vsub (dp, planet[p].pos, pos);
  563.  
  564.     rr = Mag2 (dp);
  565.  
  566.     /* Ignore planets too far away */
  567.     if (rr > 200.0*200.0) continue;
  568.  
  569.     /* Don't stand so close to me */
  570.     if (rr < RMIN) rr = RMIN;
  571.  
  572.     r = sqrt (rr);
  573.     dv = G * planet[p].mass / rr;
  574.  
  575.     Vmul (v, dp, dv);
  576.     Vdiv (v, v, r);
  577.  
  578.     Vadd (deltav, deltav, v);
  579.   }
  580. }
  581.  
  582. void Junk()
  583. /*
  584.  *  Draw space junk to give visual cues of motion
  585.  */
  586. {
  587.   float x, y, z;
  588.  
  589.   glDisable (GL_LIGHTING);
  590.   glDisable (GL_CULL_FACE);
  591.   glColor3f (0.5, 0.5, 0.5);
  592.  
  593.   x = (float)(int)player.pos[0];
  594.   y = (float)(int)player.pos[1];
  595.   z = (float)(int)player.pos[2];
  596.  
  597.   PieceOfJunk (x+0.5, y+0.5, z+0.5);
  598.   PieceOfJunk (x-0.5, y+0.5, z+0.5);
  599.   PieceOfJunk (x-0.5, y-0.5, z+0.5);
  600.   PieceOfJunk (x+0.5, y-0.5, z+0.5);
  601.  
  602.   PieceOfJunk (x+0.5, y+0.5, z-0.5);
  603.   PieceOfJunk (x-0.5, y+0.5, z-0.5);
  604.   PieceOfJunk (x-0.5, y-0.5, z-0.5);
  605.   PieceOfJunk (x+0.5, y-0.5, z-0.5);
  606.  
  607.   glEnable (GL_CULL_FACE);
  608.   glEnable (GL_LIGHTING);
  609. }
  610.  
  611. void PieceOfJunk (float x, float y, float z)
  612. /*
  613.  *  Draw a single piece of space junk
  614.  */
  615. {
  616.   float r;
  617.   double v1[3], v2[3];
  618.  
  619.   glPushMatrix();
  620.  
  621.   /* Figure how much to spin junk */
  622.   r = (float)absT - ((float)(int)absT);
  623.   r *= 360.0;
  624.  
  625.   /* Draw the junk */
  626.   v1[0] = (double)x; v1[1] = (double)y; v1[2] = (double)z;
  627.   Vsub (v2, v1, player.pos);
  628.   glTranslated (v2[0], v2[1], v2[2]);
  629.  
  630.   glRotatef (r, 0.0, 1.0, 0.0);
  631.   glBegin (GL_POLYGON);
  632.   glNormal3f (0.0, 0.0, 1.0);
  633.   glVertex3f (-.003, -.003, 0.0);
  634.   glVertex3f (.003, -.003, 0.0);
  635.   glVertex3f (0.0, .003, 0.0);
  636.   glEnd();
  637.  
  638.   glPopMatrix();
  639. }
  640.  
  641. void ShowNames()
  642. /*
  643.  *  Show the names of things
  644.  */
  645. {
  646.   glDisable (GL_DEPTH_TEST);
  647.   glDisable (GL_LIGHTING);
  648.   ShowPlanetNames();
  649.   ShowTargetNames();
  650.   glEnable (GL_LIGHTING);
  651.   glEnable (GL_DEPTH_TEST);
  652. }
  653.  
  654. void LookAt (double *view, double *up)
  655. /*
  656.  *  Set up a transformation so a model will be drawn pointing the
  657.  *  right direction (view) and upright (up)
  658.  */
  659. {
  660.   double v1[3],
  661.   v2[3],
  662.   up2[3];
  663.   float  th,
  664.   thd;
  665.  
  666.   /*
  667.   *  This thing is really ugly and inefficient.  It does sqrt's,
  668.   *  sin's, cos's, acos's, and asin's like there's no tomorrow.
  669.   *
  670.   *  In theory we should be able to build a little matrix like
  671.   *  gluLookAt() does, but I could never get that to work.  I
  672.   *  suspect what's needed is the inverse or transpose of the
  673.   *  gluLookAt() matrix, but I don't understand linear algebra
  674.   *  well enough to know.
  675.   *
  676.   *  If you can improve this thing please let me know.
  677.   */
  678.  
  679.   /* Make vector along positive X axis */
  680.   v1[0] = 1.0;
  681.   v1[1] =
  682.   v1[2] = 0.0;
  683.  
  684.   /* Cross-product of X-axis and view vector is vector to
  685.     rotate about */
  686.   Crossp (v2, v1, view);
  687.  
  688.   /* Check for special case of null v2 (vectors are the same) */
  689.   if (!Mag2(v2)) v2[1] = 1.0;
  690.  
  691.   /* Normalize the vector to rotate about */
  692.   Normalize (v2);
  693.  
  694.   /* Compute angle to rotate */
  695.   th = (float)acos (Dotp(view, v1));
  696.  
  697.   /* Now we've got the model pointed in the right direction,
  698.     but the up vector is probably wrong.  This is the only
  699.     way I could think of to do this but boy it's ugly. */
  700.  
  701.   /* Figure out new up vector in up2 */
  702.   v1[0] = v1[1] = 0.0;
  703.   v1[2] = 1.0;
  704.   RotateAbout (up2, v1, v2, -th);
  705.   Normalize (up2);
  706.  
  707.   /* Rotate */
  708.   glRotatef (th * (float)57.29577951308, (float)v2[0], (float)v2[1], (float)v2[2]);
  709.  
  710.   /* Cross product of current up and desired up is vector
  711.     to rotate about */
  712.   Crossp (v2, up2, up);
  713.  
  714.   /* If v2 is null, we're already facing the right way */
  715.   if (!Mag2(v2)) return;
  716.  
  717.   Normalize (v2);
  718.   thd = acos(Dotp(up2, up)) * 57.29577951308;
  719.  
  720.   /* We rotate around the (rotated) view vector or negative view
  721.     vector depending which way v2 points */
  722.   if (Dotp(v2, view) > 0.0)
  723.   glRotatef (thd, 1.0, 0.0, 0.0);
  724.   else
  725.   glRotatef (thd, -1.0, 0.0, 0.0);
  726. }
  727.